
#include "GLcamera.h"

GLcamera::GLcamera(void)
{
	m_translate.Clear();
	m_rotate.Clear();

	//m_translate.x = -50;
	//m_translate.z = -200.f;

	//m_rotate.y = 45.f;

	m_up[0] = 0.f;m_up[1] = 1.f;m_up[2] = 0.f;

	m_speed_fw = 1.f;
	m_speed_lr = 1.f;
	m_speed_ud = 1.f;

	m_speed_pan[0] = m_speed_pan[1] = 1.f;
	m_speed_rotate[0] = m_speed_rotate[1] = m_speed_rotate[2] = 1.f;

	m_next_move.Clear();
}

GLcamera::~GLcamera(void)
{
}

GLmat4f GLcamera::GetBillboardMatrix()
{
	GLmat4f m1,m2,m3,m;
	
	m1.MakeRotateX( m_rotate[0] );
	m2.MakeRotateY( m_rotate[1] );
	m3.MakeRotateZ( m_rotate[2] );

	m = m3* m1;

	return m;
}

void GLcamera::GetRotateMatrix( GLmat4f& m )
{
	GLmat4f m1;
	GLmat4f m2;
	GLmat4f m3;
	GLmat4f mx;

	GLvec3f right =  GLvec3f(1,0,0);
	GLvec3f up = GLvec3f(0,1,0);
	GLvec3f forward = GLvec3f( 0,0,1 );
	

	m1.MakeRotate( m_rotate[0],right );
	m2.MakeRotate( m_rotate[1],up );
	m3.MakeRotate( m_rotate[2],forward );

	mx = m2*m1;
	m = mx*m3;

}

void GLcamera::YawPitchRoll( float pitch,float yaw,float roll )
{
	m_rotate[0] += pitch * m_speed_rotate[0];
	m_rotate[1] += yaw * m_speed_rotate[1];
	m_rotate[2] += roll * m_speed_rotate[2];

	if( m_rotate[0] > 90.f)
		m_rotate[0] = 90.f;
	if( m_rotate[0] < -90.f)
		m_rotate[0] = -90.f;

}

void GLcamera::Update()
{
#if 1
	GLmat4f m1,m2;

	GetRotateMatrix( m1 );
	
	m2 = m1;

	GLvec3f translate = m2.TransformVec3( m_translate );

	m1.w.x = translate.x;
	m1.w.y = translate.y;
	m1.w.z = translate.z;

	m_view = m1;

	glLoadMatrixf( m_view.Base());

	m_next_move.Clear();
#else
	glRotatef( m_rotate.x,1,0,0);
	glRotatef( m_rotate.y,0,1,0);
	glRotatef( m_rotate.z,0,0,1);
	
	glTranslatef( m_translate.x,m_translate.y,m_translate.z );
#endif

}
GLvec3f GLcamera::GetPosition()
{
	GLvec3f pos = m_translate;
	pos.Negative();
	return pos;
}
void GLcamera::Pan( float x,float y )
{
	GLmat4f m;
	GLvec3f right,forward,real_up;

	GetRotateMatrix( m );

	GL_GetRightVec( m,right);
	GL_GetForwardVec( m,forward );

	real_up = right.CrossProd( forward );

	real_up.Normalize();
	real_up.Scale(y*m_speed_pan[1]);
	m_translate.Add( real_up );

	right.Normalize();
	right.Scale( x*m_speed_pan[0] );

	PreMove( right );
}

void GLcamera::Raise( float step )
{
	GLvec3f vin (0.f,-1.f,0.f);
	GLvec3f vout;

	vout = vin;
	vout.Scale( step*m_speed_ud );

	PreMove( vout );
}

void GLcamera::Advance( float step )
{
	GLvec3f vin (0.f,0.f,1.f);
	GLvec3f vout;

	GLmat4f m1;
	m1.MakeRotateY( -m_rotate[1]);

	GLmat4f m2;

	m2.MakeRotateX( -m_rotate[0] );

	GLmat4f m = m2*m1;

	vout = m.TransformVec3( vin );
	vout.Scale( step*m_speed_fw );

	PreMove( vout );
}

void GLcamera::Stride(float step)
{
	GLvec3f vin (1.f,0.f,0.f);
	GLvec3f vout;

	GLmat4f m;

	m.MakeRotateY( -m_rotate[1]);

	vout = m.TransformVec3( vin );
	vout.Scale( step * m_speed_lr );

	PreMove( vout );
}

void GLcamera::MoveBackward()
{
	Advance( -1.f );
}

void GLcamera::MoveForward()
{
	Advance( 1.f );
}

void GLcamera::StrideLeft()
{
	Stride( 1.f );
}

void GLcamera::StrideRight()
{
	Stride( -1.f );
}

void GLcamera::Move( GLvec3f mov ){
	m_translate.Add( mov );
}

void GLcamera::PreMove( GLvec3f mov ){
	m_next_move = mov;
}